package com.gimi.cloud.jimi.commonService.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.gimi.cloud.jimi.common.utils.CommonUtil;
import com.gimi.cloud.jimi.commonService.service.CoreApiLogService;
import com.gimi.cloud.jimi.entity.core.ApiConfig;
import com.gimi.cloud.jimi.entity.core.ApiLog;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * API日志请求接口
 * 
 * @author wbj
 * @date 2016年12月15日
 */
public class APIHttpClientUtil {
	private static final Logger log = LoggerFactory.getLogger(APIHttpClientUtil.class);

	/**
	 * 根据API配置发送请求
	 * @param apiConfig api配置参数
	 * @param params 请求参数
	 * @param header 请求头
	 * @param showLog 是否显示日志信息
	 * @return map:success:true|false, resultStr:请求返回结果
	 */
	public static Map<String,Object> sendGet(ApiConfig apiConfig, Map<String, String> params, Map<String, String> header, boolean showLog) {
		String result = "";
		Map<String,Object> resultMap = new HashMap<String,Object>();
		BufferedReader in = null;
		ApiLog apiLog = new ApiLog();
		apiLog.setLogDate(new Date());
		boolean isSuccess = false;
		CoreApiLogService apiLogService = (CoreApiLogService) BeanUtil.getBean("coreApiLogService");
		try {
			if (null != apiConfig) {
				if(showLog) log.info("开始执行"+apiConfig.getName());
				apiLog.setLogType(apiConfig.getNid());
				if (StringUtils.isNotBlank(apiConfig.getUrl())) {// 请求地址不为空
					String url = apiConfig.getUrl().indexOf("?") != -1 ? apiConfig.getUrl() : apiConfig.getUrl() + "?date=" + new Date().getTime();
					String charset = StringUtils.isBlank(apiConfig.getCharset()) ? "utf-8" : apiConfig.getCharset();
					StringBuffer buffer = new StringBuffer("&");
					JSONObject json = new JSONObject();
					if (CommonUtil.isJson(apiConfig.getParams())) {
						String apiparam = apiConfig.getParams();
						if(null != params && !params.isEmpty()){
							for(String key:params.keySet()){
								if(key.indexOf(":") == 0){//特殊标记，以:开口则代表传入的值，并替换该值，后续便于更新接口
									apiparam = apiparam.replaceAll(key, params.get(key));
								}
							}
						}
						json = JSON.parseObject(apiparam);
					}
					if (null != params && params.size() > 0){
						json.putAll(params);
					}
					for (String str : json.keySet()) {// 组装params
						if (StringUtils.isNotBlank("" + json.get(str)) && str.indexOf(":") != 0) {//排除传入的引用参数
							Object strValue = json.get(str);
							if (strValue.getClass().equals(JSONArray.class)) {//如果是数组类型，则随机抽取一个作为密钥
								JSONArray values = json.getJSONArray(str);
								if (values.size() > 0) {
									buffer.append(str).append("=").append(URLEncoder.encode("" + values.get(getRandomNum(0, values.size() - 1)), charset)).append("&");
								}
							} else {
								buffer.append(str).append("=").append(URLEncoder.encode(json.getString(str), charset)).append("&");
							}
						}
					}
					buffer.deleteCharAt(buffer.length() - 1);// 截取末尾&
					apiLog.setLogParam(JSON.toJSONString(json));
					if (showLog) {
						log.info("====开始发送get请求==========");
						log.info("===请求地址：" + url + buffer.toString());
						log.info("===请求编码：" + charset);
					}
					URL realUrl = new URL(url + buffer.toString());
					URLConnection connection = realUrl.openConnection();// 打开和URL之间的连接
					connection.setRequestProperty("accept", "*/*");// 设置通用的请求属性
					connection.setRequestProperty("connection", "Keep-Alive");
					connection.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
					
					//设置超时(2017-03-19)wangw
					connection.setConnectTimeout(30000);  
					connection.setReadTimeout(30000);  
					
					json = new JSONObject();
					if (CommonUtil.isJson(apiConfig.getHeader())) { // 组装默认的请求头信息
						String apiHeader = apiConfig.getHeader();
						if(null != header && !header.isEmpty()){
							for(String key:header.keySet()){//特殊标记，以:开口则代表传入的值，并替换该值，后续便于更新接口
								if(key.indexOf(":") ==0){
									apiHeader = apiHeader.replaceAll(key, header.get(key));
								}
							}
						}
						json = JSON.parseObject(apiHeader);
					}
					if (null != header) {
						json.putAll(header);
					}
					for (String str : json.keySet()) { // 组装header
						if (StringUtils.isNotBlank("" + json.get(str)) && str.indexOf(":") != 0) {//排除传入的引用参数
							Object strValue = json.get(str);
							if (strValue.getClass().equals(JSONArray.class)) {
								JSONArray values = json.getJSONArray(str);
								if (values.size() > 0) {
									connection.setRequestProperty(str,"" + values.get(getRandomNum(0, values.size() - 1)));
								}
							} else {
								connection.setRequestProperty(str, "" + strValue);
							}
						}
					}
					connection.connect();// 建立实际的连接
					in = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset));// 定义
					String line;
					while ((line = in.readLine()) != null) {
						result += line;
					}
					apiLog.setLogResponse(result);
					String code = "";
					if (CommonUtil.isJson(result) && StringUtils.isNotBlank(apiConfig.getCodePath())) {
						json = JSON.parseObject(result);
						String[] codePath = apiConfig.getCodePath().replace("，", ",").split(",");
						for (int i = 0; i < codePath.length; i++) {
							if (json.containsKey(codePath[i])) {
								if ((i + 1) == codePath.length) {
									code = json.getString(codePath[i]);
								} else {
									json = json.getJSONObject(codePath[i]);
								}
							}
						}
					}
					apiLog.setLogCode(code);
					if (StringUtils.isBlank(apiConfig.getRealCode()) || apiConfig.getRealCode().equals(code)) {
						isSuccess = true;
					}
					apiLogService.updateLogTimes(apiConfig.getId(), isSuccess);
					if (showLog)
						log.info("===Get请求成功：" + result);
				} else {
					throw new Exception("类型为" + apiConfig.getNid() + "的API接口未配置请求地址，请检查!");
				}
				if(showLog) log.info("执行完成"+apiConfig.getName());
			} else {
				log.info("发送Http请求错误，未传入配置参数!");
			}
		} catch (Exception e) {
			e.printStackTrace();
			if(StringUtils.isNotBlank(apiConfig.getBackupNid()) && Global.API_CONFIG.containsKey(apiConfig.getBackupNid())){
				apiLogService.addApiLog(apiLog);
				ApiConfig newApiConfig = Global.API_CONFIG.get(apiConfig.getBackupNid());
				log.info("接口"+apiConfig.getName()+apiConfig.getNid()+"调用失败，自动切换至备份接口"+newApiConfig.getName()+newApiConfig.getBackupNid());
				return sendGet(Global.API_CONFIG.get(apiConfig.getBackupNid()),params,header,showLog);
			}
		} finally {
			try {
				if (in != null)
					in.close();// 关闭输入流
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		if (!isSuccess) {// 如果记录不成功，则保存数据
			apiLogService.addApiLog(apiLog);
		}
		resultMap.put("success", isSuccess?"true":"false");
		resultMap.put("resultStr", result);
		resultMap.put("apiconfig", apiConfig);
		return resultMap;
	}
	
	/**
	 * 根据类型及参数发送请求并处理结果
	 * @param type 配置类型
	 * @param params 请求参数
	 * @param showLog 是否显示日志
	 * @return 请求结果
	 */
	public static String getResultByApiConfig(String type,Map<String,String> params,Map<String,String> header,boolean showLog){
		String result = "";
		try {
			if(StringUtils.isNotBlank(type) && Global.API_CONFIG.containsKey(type)){
//				log.info("----------------Global.API_CONFIG.get(type):" + Global.API_CONFIG.get(type));
				ApiConfig apiConfig = Global.API_CONFIG.get(type);
				Map<String,Object > resultStr = sendGet(apiConfig,params,header,showLog);
				apiConfig = ApiConfig.getInstance(resultStr.get("apiconfig")); //避免调用备份接口解析数据异常，此方法切换API接口配置数据
				result =""+resultStr.get("resultStr");
				if(CommonUtil.isJson(apiConfig.getResult()) && CommonUtil.isJson(result) && "true".equals(resultStr.get("success"))){
					JSONObject jsonResult = JSON.parseObject(apiConfig.getResult());
					JSONObject data = JSON.parseObject(result);
					if(jsonResult.containsKey("path")&& StringUtils.isNotBlank(jsonResult.getString("path")) && jsonResult.containsKey("type") && "json".equals(jsonResult.get("type"))){//返回结果是JSON数据才做处理
						String[] paths = jsonResult.getString("path").split("-");//获取结果路径
						String path="";
						String separator = jsonResult.containsKey("separator")?""+jsonResult.get("separator"):"";
						result ="";
						for(int i=0;i<paths.length;i++){
							path = paths[i];
							if(i == paths.length - 1){//到达末尾
								for(String str:path.split(",")){
									result += data.getString(str)+separator;
								}
								if(StringUtils.isNotBlank(separator)){
									result = result.substring(0, result.length()-separator.length());
								}
							}else{
								data = data.getJSONObject(paths[i]);
							}
						}
						if(jsonResult.containsKey("replace")){//处理返回结果
							jsonResult = jsonResult.getJSONObject("replace");
							for(String key:jsonResult.keySet()){
								result =  result.replaceAll(key, jsonResult.getString(key));
							}
						}
					}
				}else{
					log.info(result);
					result ="";
				}
			}else{
				throw new Exception("未获取到type为："+type+"的apiConfig,请检查");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 获取指定范围内的随机数
	 * 
	 * @param min
	 *            最小值（包含）
	 * @param max
	 *            最大值（不包含）
	 * @return 获取的随机数
	 */
	private static int getRandomNum(int min, int max) {
		Random random = new Random();
		return random.nextInt(max) % (max - min + 1) + min;
	}
}
